public with sharing class ClsOppChangeCloseDate {
	private ApexPages.StandardController stdCtrl; 
	
	public List<ClsOppLineItemWrapper> oliwrapper {get; set;}
	public List<OpportunityLineItem> OppProds {get; set;}
 
	public Date oldDate {get; set;}
	public Date newDate {get; set;}
	public Integer difDate {get; set;} 

	public Opportunity chOpp {get; set;}


	public ClsOppChangeCloseDate(ApexPages.StandardController std){
		stdCtrl=std;
	} 

	public void init(){
		chOpp = [SELECT Id, Name, CloseDate, NewDate__c FROM Opportunity WHERE Id = :stdCtrl.getId()];
		oldDate = chOpp.CloseDate;
		newDate = oldDate;
		chOpp.NewDate__c = chOpp.CloseDate;
		
		OppProds = [SELECT Id, ServiceDate, PricebookEntryId,  OpportunityId FROM OpportunityLineItem WHERE OpportunityId = :chOpp.Id AND (ServiceDate >= today OR ServiceDate < today)];
		oliwrapper = new List<ClsOppLineItemWrapper> ();
		if(OppProds.size()>0){
		for ( OpportunityLineItem oneoli : OppProds){
				ClsOppLineItemWrapper oliw2 = new ClsOppLineItemWrapper();
				oliw2.oppItem = oneoli;
				oliw2.oppNewDate = oneoli.ServiceDate;
				oliw2.pbeName = [Select Id, Name From PricebookEntry WHERE Id = :oneoli.PricebookEntryId LIMIT 1];
				oliwrapper.add(oliw2);
			}
		}
	} // end init(); 

	// Step 1
	public Pagereference  savenewdate(){
		newDate = chOpp.NewDate__c;
		update chOpp;
		difDate = oldDate.daysBetween(newDate);
		// Step 2
		saveclosedate();
		// Step 3
		showNewclosedateToOpportunityLineItems();
		// Step 4
		saveNewclosedateToOpportunityLineItems();
		//PageReference pageRef = new PageReference('/' + chOpp.Id);
		PageReference pageRef = new ApexPages.StandardController(chOpp).view();
		pageRef.setRedirect(true);
		return pageRef;
	}
	
	// Step 2
	public void saveclosedate(){
		chOpp.CloseDate = newDate;
		update chOpp;
	}
	
	// Step 3
	public void showNewclosedateToOpportunityLineItems(){
		// here we will loop the wrapper and modify the service date
		for(Integer i = 0; i < oliwrapper.size(); i++){
			oliwrapper[i].oppNewDate = oliwrapper[i].oppNewDate.addDays(difDate); 
		}
		
		// here we will save the 
	}
	
	// Step 4
	public void saveNewclosedateToOpportunityLineItems(){
		if(OppProds.size()>0){
			OppProds.clear();
			for(Integer i = 0; i < oliwrapper.size(); i++){
				oliwrapper[i].oppItem.ServiceDate =	oliwrapper[i].oppNewDate; 
				OppProds.add(oliwrapper[i].oppItem);
			}
			update OppProds;
		}
	}


	// Step 5
	public void testlocals(){
		oldDate = chOpp.CloseDate;
		newDate = chOpp.NewDate__c;
		difDate = oldDate.daysBetween(newDate);
	}
    
    	
    static testMethod void myTest() {
       
        Account testaccount = new Account (Name = 'TestAccount');
        insert testaccount;
        
        // onedate
        Date onedate = Date.valueOf('2009-04-04');
        
        // testopportunity
        Opportunity testopportunity = new Opportunity (Name = 'TestOpp', 
        							StageName = 'Prospecting', 
        							CloseDate = onedate, 
        							AccountId = testaccount.Id);
        insert testopportunity;
        
		// pb = standart Pricebook
		Pricebook2 pb =[select name,isactive from Pricebook2 where isStandard=true];
		if(!pb.isactive){
		pb.isactive=true;
		Database.update(pb);
		}
		
		// stage = OpportunityStage for Masterlabel
		OpportunityStage stage=[select Masterlabel from OpportunityStage where Masterlabel != '' limit 1];
		
		// opp = Opportunity
		Opportunity opp = new Opportunity();
		opp.Name='TestOpp';
		opp.AccountID=testaccount.id;
		opp.CloseDate = onedate;
		opp.NewDate__c = onedate;
		opp.StageName=stage.masterlabel;
		opp.Pricebook2Id=pb.id;
		insert opp;
		
		// testproduct p = Product
		Product2 p = new Product2();
		p.Name='TestProd';
		p.Produktname_lang__c = 'TestHeaderDescription';
		p.IsActive = true;
		insert p;
		
		// sumTotalPrice = double
		double sumTotalPrice = 2.0;
		
		// SumOfPhase = double
		double SumOfPhase = 0.0;
		
		//pbe = pricebook entry
		PricebookEntry pbe=new PricebookEntry();
		pbe.Pricebook2Id=pb.id;
		pbe.Product2Id=p.id;
		pbe.UnitPrice = sumTotalPrice;
		pbe.IsActive=true;
		insert pbe;
		
		// oli = OpportunityLineItem
		OpportunityLineItem oli = new OpportunityLineItem();
		oli.OpportunityId = opp.Id;
		oli.PricebookEntryId = pbe.Id;
		oli.ServiceDate = onedate;
		oli.Quantity = 2.0;
		oli.TotalPrice = oli.Quantity * sumTotalPrice;
		insert oli;

		
		//user
		Profile admin = [select id, name, PermissionsModifyAllData from Profile where PermissionsModifyAllData = TRUE LIMIT 1]; 
    	User testusers = [select email, id, name, ProfileId from user where isActive=true and ProfileId= :admin.Id LIMIT 1];
		//system.debug('username' + testusers.name);
		
		// ClsOppLineItemWrapper
		ClsOppLineItemWrapper twrapper = new ClsOppLineItemWrapper();
		twrapper.oppItem = oli;
		twrapper.oppNewDate = onedate;
		twrapper.pbeName = pbe;
		
		System.assertEquals(twrapper.oppItem.Id, oli.Id);
		System.assertEquals(twrapper.oppNewDate, onedate);
		System.assertEquals(twrapper.pbeName.Id, oli.PricebookEntryId);
		
		// generate page
    	PageReference pageRef = Page.Change_Opportunity_Close_Date;
    	pageRef.getParameters().put('id', opp.id); 
    	Test.setCurrentPage(pageRef);
    	
		ApexPages.Standardcontroller controller = New ApexPages.StandardController(opp);
        ClsOppChangeCloseDate ext = new ClsOppChangeCloseDate(controller);
        ext.init();
        String nextPage = controller.save().getUrl();
        string testOppId = '/' + opp.Id;
        // Verify that page fails without parameters  
        System.assertEquals( testOppId.substring(0,16),  nextPage.substring(0,16));
        
        ext.chOpp.NewDate__c = onedate.addDays(10);
        ext.savenewdate();
        System.assert(ext.difDate == 10);
        System.assert(ext.newDate == onedate.addDays(10));
        system.assert(ext.oldDate == onedate);
        system.assert(ext.chOpp.Id == opp.Id);
        system.assert(ext.OppProds[0].Id == oli.Id);
        
/*       	public void testlocals(){
		oldDate = chOpp.CloseDate;
		newDate = chOpp.NewDate__c;
		difDate = oldDate.daysBetween(newDate);
*/
		ext.testlocals();
		System.assert(ext.difDate == 0);
        System.assert(ext.newDate == onedate.addDays(10));
        system.assert(ext.oldDate == onedate.addDays(10));
    } // end testmethod
} // end class ClsOppChangeCloseDate




/*	public Date newDate;
	public void setnewDate(Date newDate2)  {
		newDate = newDate2;
		chOpp.NewDate__c = newDate;
	}
	public Date getnewDate(){
		newDate = chOpp.NewDate__c;
		return newDate;
	} 

	//public Opportunity chOpp;
*/	
/*	public void setchOpp(Opportunity chOpp2){
		chOpp = chOpp2;
		update chOpp;
	}
	public Opportunity getchOpp(){
		chOpp = [SELECT Id, Name, CloseDate, NewDate__c FROM Opportunity WHERE Id = :stdCtrl.getId()];
		return chOpp;
	}
*/

/*	public PageReference save() {
		stdCtrl.save();
		chOpp = [SELECT Id, Name, CloseDate, NewDate__c FROM Opportunity WHERE Id = :stdCtrl.getId()];
		newDate = chOpp.NewDate__c;
		//newtoolddate();
		stdCtrl.save();
		return Apexpages.currentPage();
	}
*/

/*		PageReference prChOpDt = new PageReference('https://c.cs7.visual.force.com/apex/Change_Opportunity_Close_Date?id=006M0000002lMat'); 
		return Apexpages.currentPage();
		try{
			stdCtrl.save();
		} catch (Dmlexception ex2){
			ApexPages.addMessages(ex2);
		}
*/